//
//  JTButton.swift
//  TestUIKit
//
//  Created by Kiyo on 2021/4/9.
//

import UIKit

public enum JTButtonImagePosition {
    case top
    case left
    case right
    case bottom
}


public class JTButton: UIButton {

    /// 设置图文排列方向
    public var imagePosition: JTButtonImagePosition = .left {
        didSet {
            setNeedsLayout()
        }
    }
    
    /// 图文间距
    public var space: CGFloat = 0 {
        didSet {
            setNeedsLayout()
        }
    }
 
    
    
    
    
    
    public override var intrinsicContentSize: CGSize {
        return sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
    }
    
    public override func sizeThatFits(_ size: CGSize) -> CGSize {
        
        var tempSize: CGSize = size
        
        if bounds.size == size {
            tempSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
        }
        
        let isImageViewShowing: Bool = currentImage == nil ? false : true
        let isTitleLabelShowing: Bool = currentTitle == nil ? false : true
        
        var imageTotalSize: CGSize = .zero
        var titleTotalSize: CGSize = .zero
        var resultSize: CGSize = .zero
        let tempSpace: CGFloat = isImageViewShowing && isTitleLabelShowing ? space : 0
        let contentLimitSize: CGSize = CGSize(width: tempSize.width - contentEdgeInsets.horizontalValue,
                                              height: tempSize.height - contentEdgeInsets.verticalValue)
        
        switch (imagePosition) {
        case .top, .bottom:
                if (isImageViewShowing) {
                    let imageLimitWidth: CGFloat = contentLimitSize.width - imageEdgeInsets.horizontalValue
                    var imageSize: CGSize = currentImage?.size ?? .zero
                    imageSize.width = min(imageSize.width, imageLimitWidth)
                    imageTotalSize = CGSize(width: imageSize.width + imageEdgeInsets.horizontalValue,
                           height: imageSize.height + imageEdgeInsets.verticalValue)
                }
                
                if (isTitleLabelShowing) {
                    let titleLimitSize: CGSize = CGSize(width: contentLimitSize.width - titleEdgeInsets.horizontalValue, height: contentLimitSize.height - imageTotalSize.height - tempSpace - titleEdgeInsets.verticalValue)
                    var titleSize = titleLabel?.sizeThatFits(titleLimitSize) ?? .zero
                    titleSize.height = min(titleSize.height, titleLimitSize.height)
                    titleTotalSize = CGSize(width: titleSize.width + titleEdgeInsets.horizontalValue, height: titleSize.height + titleEdgeInsets.verticalValue)
                }
                
            resultSize.width = contentEdgeInsets.horizontalValue
                resultSize.width += max(imageTotalSize.width, titleTotalSize.width);
            resultSize.height = contentEdgeInsets.verticalValue + imageTotalSize.height + tempSpace + titleTotalSize.height;
        case .left, .right:
                if (isImageViewShowing) {
                    let imageLimitHeight: CGFloat = contentLimitSize.height - imageEdgeInsets.verticalValue
                    var imageSize: CGSize = currentImage?.size ?? .zero
                    imageSize.height = min(imageSize.height, imageLimitHeight)
                    imageTotalSize = CGSize(width: imageSize.width + imageEdgeInsets.horizontalValue, height: imageSize.height + imageEdgeInsets.verticalValue)
                }
                
                if (isTitleLabelShowing) {
                    let titleLimitSize: CGSize = CGSize(width: contentLimitSize.width - titleEdgeInsets.horizontalValue - imageTotalSize.width - tempSpace,
                                                        height: contentLimitSize.height - titleEdgeInsets.verticalValue)
                    var titleSize = titleLabel?.sizeThatFits(titleLimitSize) ?? .zero
                    titleSize.height = min(titleSize.height, titleLimitSize.height);
                    titleTotalSize = CGSize(width: titleSize.width + titleEdgeInsets.horizontalValue,
                                            height: titleSize.height + titleEdgeInsets.verticalValue)
                }
                
            resultSize.width = contentEdgeInsets.horizontalValue + imageTotalSize.width + tempSpace + titleTotalSize.width
            resultSize.height = contentEdgeInsets.verticalValue
                resultSize.height += max(imageTotalSize.height, titleTotalSize.height)
        }
        return resultSize
    }
    
    public override func layoutSubviews() {
        super.layoutSubviews()
        
        guard !bounds.isEmpty else { return }
        
        let isImageViewShowing: Bool = currentImage == nil ? false : true
        let isTitleLabelShowing: Bool = currentTitle == nil ? false : true
        
        var imageLimitSize: CGSize = .zero
        var titleLimitSize: CGSize = .zero
        var imageTotalSize: CGSize = .zero
        var titleTotalSize: CGSize = .zero
        var imageFrame: CGRect = .zero
        var titleFrame: CGRect = .zero
        
        let contentSize: CGSize = CGSize(width: bounds.width - contentEdgeInsets.horizontalValue,
                                         height: bounds.height - contentEdgeInsets.verticalValue)
        
        if isImageViewShowing {
            imageLimitSize = CGSize(width: contentSize.width - imageEdgeInsets.horizontalValue,
                                    height: contentSize.height - imageEdgeInsets.verticalValue)
            var imageSize: CGSize = currentImage?.size ?? .zero
            imageSize = CGSize(width: min(imageLimitSize.width, imageSize.width),
                               height: min(imageLimitSize.height, imageSize.height))
            imageFrame = CGRect(origin: CGPoint(x: 0, y: 0), size: imageSize)
            imageTotalSize = CGSize(width: imageSize.width + imageEdgeInsets.horizontalValue,
                                    height: imageSize.height + imageEdgeInsets.verticalValue)
        }
        
        switch imagePosition {
        case .top, .bottom:
            if isTitleLabelShowing {
                titleLimitSize = CGSize(width: contentSize.width - titleEdgeInsets.horizontalValue,
                                        height: contentSize.height - imageTotalSize.height - titleEdgeInsets.verticalValue - space)
                
                var titleSize: CGSize = titleLabel?.sizeThatFits(titleLimitSize) ?? .zero
                
                titleSize = CGSize(width: min(titleLimitSize.width, titleSize.width),
                                   height: min(titleLimitSize.height, titleSize.height))
                titleFrame = CGRect(origin: CGPoint(x: 0, y: 0), size: titleSize)
                titleTotalSize = CGSize(width: titleSize.width + titleEdgeInsets.horizontalValue,
                                        height: titleSize.height + titleEdgeInsets.verticalValue)
            }
            
            switch contentHorizontalAlignment {
            case .left:
                if isImageViewShowing {
                    imageFrame.origin.x = contentEdgeInsets.left + imageEdgeInsets.left
                }
                if isTitleLabelShowing {
                    titleFrame.origin.x = contentEdgeInsets.left + titleEdgeInsets.left
                }
            case .center:
                if isImageViewShowing {
                    imageFrame.origin.x = contentEdgeInsets.left + imageEdgeInsets.left + (imageLimitSize.width - imageFrame.width)/2
                }
                if isTitleLabelShowing {
                    titleFrame.origin.x = contentEdgeInsets.left + imageEdgeInsets.left + (titleLimitSize.width - titleFrame.width)/2
                }
            case .right:
                if isImageViewShowing {
                    imageFrame.origin.x = bounds.width - contentEdgeInsets.right - imageEdgeInsets.right - imageFrame.width
                }
                if isTitleLabelShowing {
                    titleFrame.origin.x = bounds.width - contentEdgeInsets.right - titleEdgeInsets.right - titleFrame.width
                }
            case .fill:
                if (isImageViewShowing) {
                    imageFrame.origin.x = contentEdgeInsets.left + imageEdgeInsets.left
                    imageFrame.size.width = imageLimitSize.width
                }
                if (isTitleLabelShowing) {
                    titleFrame.origin.x = contentEdgeInsets.left + titleEdgeInsets.left
                    titleFrame.size.width = titleLimitSize.width
                }
            default:
                break
            }
            
            if imagePosition == .top {
                switch contentVerticalAlignment {
                case .top:
                    if isImageViewShowing {
                        imageFrame.origin.y = contentEdgeInsets.top + imageEdgeInsets.top
                    }
                    if isTitleLabelShowing {
                        titleFrame.origin.y = contentEdgeInsets.top + imageTotalSize.height + titleEdgeInsets.top + space
                    }
                case .center:
                    let contentHeight: CGFloat = imageTotalSize.height + titleTotalSize.height + space
                    let minY: CGFloat = (contentSize.height - contentHeight)/2 + contentEdgeInsets.top
                    if isImageViewShowing {
                        imageFrame.origin.y = minY + imageEdgeInsets.top
                    }
                    if isTitleLabelShowing {
                        titleFrame.origin.y = minY + imageTotalSize.height + titleEdgeInsets.top + space
                    }
                case .bottom:
                    if isImageViewShowing {
                        imageFrame.origin.y = bounds.height - contentEdgeInsets.bottom - titleTotalSize.height - imageEdgeInsets.bottom - imageFrame.height - space
                    }
                    if isTitleLabelShowing {
                        titleFrame.origin.y = bounds.height - contentEdgeInsets.bottom - titleEdgeInsets.bottom - titleFrame.height
                    }
                case .fill:
                    if (isImageViewShowing && isTitleLabelShowing) {
                        if isImageViewShowing {
                            imageFrame.origin.y = contentEdgeInsets.top + imageEdgeInsets.top
                        }
                        if isTitleLabelShowing {
                            titleFrame.origin.y = contentEdgeInsets.top + imageTotalSize.height + titleEdgeInsets.top + space
                            titleFrame.size.height = bounds.height - contentEdgeInsets.bottom - titleEdgeInsets.bottom - titleFrame.minY
                        }
                    } else if (isImageViewShowing) {
                        imageFrame.origin.y = contentEdgeInsets.top + imageEdgeInsets.top
                        imageFrame.size.height = contentSize.height - imageEdgeInsets.verticalValue
                    } else {
                        titleFrame.origin.y = contentEdgeInsets.top + titleEdgeInsets.top
                        titleFrame.size.height = contentSize.height - titleEdgeInsets.verticalValue
                    }
                default:
                    break
                }
            }
            else {
                switch contentVerticalAlignment {
                case .top:
                    if isImageViewShowing {
                        imageFrame.origin.y = contentEdgeInsets.top + titleTotalSize.height + imageEdgeInsets.top + space
                    }
                    if isTitleLabelShowing {
                        titleFrame.origin.y = contentEdgeInsets.top + titleEdgeInsets.top
                    }
                case .center:
                    let contentHeight: CGFloat = imageTotalSize.height + titleTotalSize.height + space
                    let minY: CGFloat = (contentSize.height - contentHeight)/2 + contentEdgeInsets.top
                    if isImageViewShowing {
                        imageFrame.origin.y = minY + titleTotalSize.height + imageEdgeInsets.top + space
                    }
                    if isTitleLabelShowing {
                        titleFrame.origin.y = minY + minY + titleEdgeInsets.top
                    }
                case .bottom:
                    if isImageViewShowing {
                        imageFrame.origin.y = bounds.height - contentEdgeInsets.bottom - imageEdgeInsets.bottom - imageFrame.height
                    }
                    if isTitleLabelShowing {
                        titleFrame.origin.y = bounds.height - contentEdgeInsets.bottom - imageTotalSize.height - titleEdgeInsets.bottom - titleFrame.height - space
                    }
                case .fill:
                    if (isImageViewShowing && isTitleLabelShowing) {
                        if isImageViewShowing {
                            imageFrame.origin.y = bounds.height - contentEdgeInsets.bottom - imageEdgeInsets.bottom - imageFrame.height
                        }
                        if isTitleLabelShowing {
                            titleFrame.origin.y = contentEdgeInsets.top + titleEdgeInsets.top
                            titleFrame.size.height = bounds.height - contentEdgeInsets.bottom - imageTotalSize.height - titleEdgeInsets.bottom - titleFrame.minY - space
                        }
                    } else if (isImageViewShowing) {
                        imageFrame.origin.y = contentEdgeInsets.top + imageEdgeInsets.top
                        imageFrame.size.height = contentSize.height - imageEdgeInsets.verticalValue
                    } else {
                        titleFrame.origin.y = contentEdgeInsets.top + titleEdgeInsets.top
                        titleFrame.size.height = contentSize.height - titleEdgeInsets.verticalValue
                    }
                default:
                    break
                }
            }
            
            if (isImageViewShowing) {
                imageView?.frame = imageFrame
            }
            if (isTitleLabelShowing) {
                titleLabel?.frame = titleFrame
            }
        case .left, .right:
            if (isTitleLabelShowing) {
                titleLimitSize = CGSize(width: contentSize.width - titleEdgeInsets.horizontalValue - imageTotalSize.width - space,
                                        height: contentSize.height - titleEdgeInsets.verticalValue)
                var titleSize: CGSize = titleLabel?.sizeThatFits(titleLimitSize) ?? .zero
                titleSize.width = min(titleLimitSize.width, titleSize.width);
                titleSize.height = min(titleLimitSize.height, titleSize.height);
                titleFrame = CGRect(origin: CGPoint(x: 0, y: 0), size: titleSize)
                titleTotalSize = CGSize(width: titleSize.width + titleEdgeInsets.horizontalValue,
                                        height: titleSize.height + titleEdgeInsets.verticalValue)
            }
            
            switch (contentVerticalAlignment) {
            case .top:
                if isImageViewShowing {
                    imageFrame.origin.y = contentEdgeInsets.top + imageEdgeInsets.top
                }
                if isTitleLabelShowing {
                    titleFrame.origin.y = contentEdgeInsets.top + titleEdgeInsets.top
                }
            case .center:
                if isImageViewShowing {
                    imageFrame.origin.y = contentEdgeInsets.top + (contentSize.height - imageFrame.height)/2 + imageEdgeInsets.top
                }
                if isTitleLabelShowing {
                    titleFrame.origin.y = contentEdgeInsets.top + (contentSize.height - titleFrame.height)/2 + titleEdgeInsets.top
                }
            case .bottom:
                if isImageViewShowing {
                    imageFrame.origin.y = bounds.height - contentEdgeInsets.bottom - imageEdgeInsets.bottom - imageFrame.height
                }
                if isTitleLabelShowing {
                    titleFrame.origin.y = bounds.height - contentEdgeInsets.bottom - titleEdgeInsets.bottom - titleFrame.height
                }
            case .fill:
                if (isImageViewShowing) {
                    imageFrame.origin.y = contentEdgeInsets.top + imageEdgeInsets.top
                    imageFrame.size.height = contentSize.height - imageEdgeInsets.verticalValue
                }
                if (isTitleLabelShowing) {
                    titleFrame.origin.y = contentEdgeInsets.top + titleEdgeInsets.top
                    titleFrame.size.height = contentSize.height - titleEdgeInsets.verticalValue
                }
            default:
                break
            }
            
            if (imagePosition == .left) {
                switch (contentHorizontalAlignment) {
                    case .left:
                        if isImageViewShowing {
                            imageFrame.origin.x = contentEdgeInsets.left + imageEdgeInsets.left
                        }
                        if isTitleLabelShowing {
                            titleFrame.origin.x = contentEdgeInsets.left + imageTotalSize.width + titleEdgeInsets.left + space
                        }
                    case .center:
                        let contentWidth: CGFloat = imageTotalSize.width + titleTotalSize.width + space
                        let minX: CGFloat = contentEdgeInsets.left + (contentSize.width - contentWidth)/2
                        if isImageViewShowing {
                            imageFrame.origin.x = minX + imageEdgeInsets.left
                        }
                        if isTitleLabelShowing {
                            titleFrame.origin.x = minX + imageTotalSize.width + titleEdgeInsets.left + space
                        }
                    case .right:
                        if (imageTotalSize.width + titleTotalSize.width + space > contentSize.width) {
                            if isImageViewShowing {
                                imageFrame.origin.x = contentEdgeInsets.left + self.imageEdgeInsets.left
                            }
                            if isTitleLabelShowing {
                                titleFrame.origin.x = contentEdgeInsets.left + imageTotalSize.width + titleEdgeInsets.left + space
                            }
                        } else {
                            if isTitleLabelShowing {
                                titleFrame.origin.x = bounds.width - contentEdgeInsets.right - titleEdgeInsets.right - titleFrame.width
                            }
                            if isImageViewShowing {
                                imageFrame.origin.x = bounds.width - contentEdgeInsets.right - titleTotalSize.width - imageTotalSize.width + imageEdgeInsets.left - space
                            }
                        }
                case .fill:
                        if (isImageViewShowing && isTitleLabelShowing) {

                            imageFrame.origin.x = contentEdgeInsets.left + imageEdgeInsets.left
                            titleFrame.origin.x = contentEdgeInsets.left + imageTotalSize.width + titleEdgeInsets.left + space
                            titleFrame.size.width = bounds.width - contentEdgeInsets.right - titleEdgeInsets.right - titleFrame.minX
                        } else if (isImageViewShowing) {
                            imageFrame.origin.x = contentEdgeInsets.left + imageEdgeInsets.left
                            imageFrame.size.width = contentSize.width - imageEdgeInsets.horizontalValue
                        } else {
                            titleFrame.origin.x = contentEdgeInsets.left + titleEdgeInsets.left
                            titleFrame.size.width = contentSize.width - titleEdgeInsets.horizontalValue
                        }
                    default:
                        break
                }
            } else {
                switch (self.contentHorizontalAlignment) {
                case .left:
                        if (imageTotalSize.width + titleTotalSize.width + space > contentSize.width) {
                            if isImageViewShowing {
                                imageFrame.origin.x = bounds.width - contentEdgeInsets.right - imageEdgeInsets.right - imageFrame.width
                            }
                            if isTitleLabelShowing {
                                titleFrame.origin.x = bounds.width - contentEdgeInsets.right - imageTotalSize.width - space - titleTotalSize.width + titleEdgeInsets.left
                            }
                        } else {
                            if isTitleLabelShowing {
                                titleFrame.origin.x = contentEdgeInsets.left + titleEdgeInsets.left
                            }
                            if isImageViewShowing {
                                imageFrame.origin.x = contentEdgeInsets.left + titleTotalSize.width + space + imageEdgeInsets.left
                            }
                        }
                case .center:
                    let contentWidth: CGFloat = imageTotalSize.width + space + titleTotalSize.width
                    let minX: CGFloat = contentEdgeInsets.left + (contentSize.width - contentWidth)/2
                    if isTitleLabelShowing {
                        titleFrame.origin.x = minX + titleEdgeInsets.left
                    }
                    if isImageViewShowing {
                        imageFrame.origin.x = minX + titleTotalSize.width + space + imageEdgeInsets.left
                    }
                case .right:
                    if isImageViewShowing {
                        imageFrame.origin.x = bounds.width - contentEdgeInsets.right - self.imageEdgeInsets.right - imageFrame.width
                    }
                    if isTitleLabelShowing {
                        titleFrame.origin.x = bounds.width - contentEdgeInsets.right - imageTotalSize.width - space - titleEdgeInsets.right - titleFrame.width
                    }
                case .fill:
                        if (isImageViewShowing && isTitleLabelShowing) {
                            imageFrame.origin.x = bounds.width - contentEdgeInsets.right - imageEdgeInsets.right - imageFrame.width
                            titleFrame.origin.x = contentEdgeInsets.left + titleEdgeInsets.left
                            titleFrame.size.width = imageFrame.minX - imageEdgeInsets.left - space - titleEdgeInsets.right - titleFrame.minX
                            
                        } else if (isImageViewShowing) {
                            imageFrame.origin.x = contentEdgeInsets.left + imageEdgeInsets.left
                            imageFrame.size.width = contentSize.width - imageEdgeInsets.horizontalValue
                        } else {
                            titleFrame.origin.x = contentEdgeInsets.left + titleEdgeInsets.left
                            titleFrame.size.width = contentSize.width - titleEdgeInsets.horizontalValue
                        }
                    default:
                        break
                }
            }
        }
        
        if (isImageViewShowing) {
            self.imageView?.frame = imageFrame
        }
        if (isTitleLabelShowing) {
            self.titleLabel?.frame = titleFrame
        }
    }
}
